package tpv;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;

/**
 * Clase principal controladora que realiza el procedimiento principal
 * del algoritmo
 * 
 * @author alex952
 */
public class Sistema
{

	private String impuestosWSDL;
	private Regla regla;
	//Atributos de la clase (UML)
	private Salida salidaDatos;
	private Entrada entradaDatos;
	private Caja caja;
	private Catalogo catalogo;

	/**
	 * Constructor genérico de la clase Sistema
	 */
	public Sistema()
	{
		this.salidaDatos = null;
		this.entradaDatos = null;
	}

	/**
	 * Función setter del atributo de impresión por la salida adecuada
	 * @param salidaDatos objeto que encapsula los método de escritura
	 * @see Salida
	 */
	public void addSalidaDatos(Salida salidaDatos)
	{
		this.salidaDatos = salidaDatos;
	}

	/**
	 * Función setter del atributo de lectura por la entrada adecuada
	 * @param entradaDatos objeto que encapsula los método de lectura
	 * @see Entrada
	 */
	public void addEntradaDatos(Entrada entradaDatos)
	{
		this.entradaDatos = entradaDatos;
	}

	/**
	 * Inicialización del sistema, creación de las cajas, asignación
	 * de los métodos de entrada y salida del sistema y carga del fichero
	 * properties para generar los métodos de cálculo de impuestos, reglas de
	 * descuentos y creación del catálogo
	 * @param rutaEntrada ruta del fichero xml de entrada
	 * @param rutaSalida ruta del ficheor xml de salida
	 */
	public void inicializar(String rutaEntrada, String rutaSalida)
	{
		caja = new Caja();
		entradaDatos = new EntradaXML(rutaEntrada);
		salidaDatos = new SalidaXML(rutaSalida);

		Properties p = new Properties();

		try
		{
			p.load(new FileInputStream("src/data/miAplicacion.properties"));

			this.impuestosWSDL = p.getProperty("Calculadora.WSDL", "http://artemisa.dlsi.ua.es/~ccachero/isi/impuestos");
			this.catalogo = new Catalogo(p.getProperty("Catalogo.URL", "http://www.dlsi.ua.es/~ccachero/catalogo.csv"));
			this.catalogo.setNumItemes(Integer.parseInt(p.getProperty("Catalogo.numItemsMemoria", "100")));
			catalogo.crearCatalogo();

			regla = rellenarReglas(p);
		}
		catch (IOException ex)
		{
			ex.printStackTrace();
			return;
		}
	}

	/**
	 * Función que trata de crear una nueva venta a partir de la entrada del
	 * sistema
	 * @return Retorna la caja en la que se ha añadido la venta
	 * @throws Exception 
	 */
	public void crearNuevaVenta() throws Exception
	{
		if (entradaDatos != null)
		{
			Venta v = entradaDatos.obtenerVenta();
			v.setCalculadoraImpuestos(new ImpuestoXML(this.impuestosWSDL));
			v.setRegla(regla);

			caja.anyadirVenta(v);
		}
		else
		{
			throw new Exception("No existe una entrada correcta de datos");
		}
	}

	/**
	 * Función que trata de añadir todas las líneas posibles de la entrada
	 * del sistema
	 * @param caja Caja en la que hay que añadir las líneas de venta
	 */
	public void anyadirLinVenta()
	{
		Integer ret = null;

		while ((ret = entradaDatos.obtenerLinVenta(this.catalogo)) != Entrada.FIN)
		{
			if (ret == Entrada.LINEA)
			{
				if (entradaDatos.getLinea().getItem() != null)
				{
					caja.anyadirLinVenta(entradaDatos.getLinea());
				}
			}
			else if (ret == Entrada.DESLINEA)
			{
				caja.deshacerLinea();
			}
			else if (ret == Entrada.DESVENTA)
			{
				caja.deshacerVenta();
				return;
			}
		}
	}

	/**
	 * Función que cierra la venta actual y la escribe por la salida del sistema
	 */
	public void cerrarVenta()
	{
		Venta venta = caja.cerrarVenta();

		salidaDatos.imprimir(venta);
	}

	private Regla rellenarReglas(Properties p)
	{
		Regla retorno = null;
		ArrayList<Regla> reglas = new ArrayList<Regla>();

		String get = null;

		if ((get = p.getProperty("DctoTarjetaFid.porcentaje")) != null)
		{
			reglas.add(new ReglaTarjeta(Double.parseDouble(get)));
		}

		if ((get = p.getProperty("DctoEmpleado.porcentaje")) != null)
		{
			reglas.add(new ReglaEmpleado(Double.parseDouble(get)));
		}

		if ((get = p.getProperty("DctoMiercoles.porcentaje")) != null)
		{
			Integer ini = Integer.parseInt(p.getProperty("DctoMiercoles.horaInicio"));
			Integer fin = Integer.parseInt(p.getProperty("DctoMiercoles.horaFin"));

			reglas.add(new ReglaMiercoles(Double.parseDouble(get), ini, fin));
		}

		String tipo = p.getProperty("DescuentosAplicables.politicaAplicacion");

		if (reglas.size() > 1)
		{
			if (tipo.equals("ACUMULABLE"))
			{
				retorno = new ReglaAcumulable(reglas);
			}
			else
			{
				retorno = new ReglaNoAcumulable(reglas);
			}
		}
		else if (reglas.size() == 1)
		{
			return reglas.get(0);
		}

		return retorno;
	}

	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args)
	{
		//Change filenames to arguments
		String file_e = "src/data/venta1.xml";
		String file_s = "src/data/ticket1.xml";

		Sistema s = new Sistema();

		try
		{
			s.inicializar(args[0], args[1]);
			s.crearNuevaVenta();
			s.anyadirLinVenta();
			s.cerrarVenta();
		}
		catch (Exception e)
		{
			System.err.println(e.getMessage());
		}
	}
}
